#pragma once

#include <functional>
#include <vector>
#include <atomic>
#include <memory>
#include <mutex>

#include "Timestamp.h"
#include "noncopyable.h"
#include "CurrentThread.h"

class Channel;
class Poller;

// 如果不设置线程数量，就至少有一个eventloop为主，对应的是Reactor
// 事件循环类 主要包含两个大模块 Channellist  Poller（epoll的抽象）
class EventLoop : noncopyable
{
public:
    using Functor = std::function<void()>;

    EventLoop();
    ~EventLoop();

    //开启事件循环
    void loop();
    //退出事件循环
    void quit();

    Timestamp pollReturnTime() const { return pollReturnTime_; }

    //在当前loop中执行
    //在TcpServer中有mainloop，当有新连接时，会getNextLoop，获取一个subloop的指针，将新连接分发出去，此时需要唤醒subloop（subloop会阻塞在epollwait）
    //然后执行subloop->queueInLoop()，会向subloop的wakeupfd发消息，然后被唤醒，执行传入的cb
    void runInLoop(Functor cb);   // 当前loop执行
    void queueInLoop(Functor cb); // 转其他loop执行

    //唤醒loop所在线程
    void wakeup();

    //EventLoop调用poller的放啊
    void updateChannel(Channel *channel);
    void removeChannel(Channel *channel);
    bool hasChannel(Channel* channel);

    //判断eventloop是否在自己的线程里面
    bool isInLoopThread() const {return threadId_ == CurrentThread::tid();}
private:
    void handleRead();//wakeup
    void doPendingFunctors();//执行回调

    using ChannelList = std::vector<Channel *>;

    std::atomic_bool looping_; // 原子操作
    std::atomic_bool quit_;    // 标识退出loop循环

    const pid_t threadId_; // 记录当前线程id

    Timestamp pollReturnTime_; // poller返回发生事件的channels的时间点
    std::unique_ptr<Poller> poller_;

    //每个subreactor监听自己的wakeupfd，发生事件后调用回调
    int wakeupFd_;                           // 主要作用是当mainLoop获取一个新用户的channel，通过算法论文选择一个subloop，通过此成员唤醒subloop
    std::unique_ptr<Channel> wakeupChannel_; // 包含一个wakeupfd

    ChannelList activeChannel_;


    std::atomic_bool callingPendingFunctors_; // 标识当前loop是否有需要执行的回调操作
    std::vector<Functor> pendingFunctors_;    // 存储loop需要执行的所有回调
    std::mutex mutex_;                        // 互斥锁用来保护上面的vector容器线程执行
};
